1 /* 2 * Hunt - a framework for web and console application based on Collie using Dlang development 3 * 4 * Copyright (C) 2015-2017 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: HuntLabs 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.application.dispatcher; 13 14 import hunt.routing; 15 import hunt.http.request; 16 import hunt.http.response; 17 18 import hunt.application.controller; 19 import hunt.application.config; 20 21 import hunt.security.acl.Manager; 22 23 import collie.utils.exception; 24 import collie.codec.http; 25 26 import std.stdio; 27 28 import std.exception; 29 import hunt.application.application; 30 import std.parallelism; 31 import hunt.security.acl.User; 32 33 class Dispatcher 34 { 35 this() 36 { 37 this._router = new Router; 38 this._router.setConfigPath(Config.path); 39 } 40 41 public 42 { 43 void dispatch(Request request) nothrow 44 { 45 try 46 { 47 Route route; 48 49 string cacheKey = request.header(HTTPHeaderCode.HOST) ~ "_" ~ request.method ~ "_" ~ request.path; 50 route = this._cached.get(cacheKey, null); 51 52 if (route is null) 53 { 54 route = this._router.match(request.header(HTTPHeaderCode.HOST), request.method, request.path); 55 56 if (route is null) 57 { 58 request.createResponse().do404(); 59 60 return; 61 } 62 63 this._cached[cacheKey] = route; 64 } 65 66 // add route's params 67 auto params = route.getParams(); 68 if (params.length > 0) 69 { 70 foreach (param, value; params) 71 { 72 request.Header().setQueryParam(param, value); 73 } 74 } 75 76 request.route = route; 77 78 79 // hunt.security filter 80 request.user = authenticateUser(request); 81 82 if (!accessFilter(request)) 83 { 84 request.createResponse().do403("no permiss to access: " ~ request.route.getController() ~ "." ~ request.route.getAction() ); 85 return; 86 } 87 88 // add handle task to taskPool 89 this._taskPool.put(task!doRequestHandle(route.handle, request)); 90 } 91 catch(Exception e) 92 { 93 showException(e); 94 } 95 } 96 97 bool accessFilter(Request request) 98 { 99 //兼容老的. 100 Identity identity = Application.getInstance().getAccessManager().getIdentity(request.route.getGroup()); 101 if (identity is null || request.route.getController().length == 0) 102 return true; 103 104 105 return request.user.can(request.route.getController() ~ "." ~ request.route.getAction()); 106 } 107 108 User authenticateUser(Request request) 109 { 110 User user; 111 Identity identity = Application.getInstance().getAccessManager().getIdentity(request.route.getGroup()); 112 if (identity !is null) 113 { 114 user = identity.login(request); 115 } 116 117 118 119 if (user is null) 120 { 121 return User.defaultUser; 122 } 123 124 return user; 125 } 126 127 128 129 void addRouteGroup(string group, string method, string value) 130 { 131 this._router.addGroup(group, method, value); 132 } 133 134 void setWorkers(TaskPool taskPool) 135 { 136 this._taskPool = taskPool; 137 } 138 139 void loadRouteGroups() 140 { 141 router.loadConfig(); 142 } 143 144 @property router() 145 { 146 return this._router; 147 } 148 } 149 150 private 151 { 152 Router _router; 153 Route[string] _cached; 154 __gshared TaskPool _taskPool; 155 } 156 } 157 158 void doRequestHandle(HandleFunction handle, Request request) 159 { 160 import hunt.http.exception; 161 162 try 163 { 164 handle(request); 165 } 166 catch (CreateResponseException e) 167 { 168 showException(e); 169 } 170 catch (Exception e) 171 { 172 showException(e); 173 174 Response response; 175 176 collectException(request.createResponse, response); 177 178 if(response) 179 { 180 collectException((){ 181 response.setHttpStatusCode(502); 182 response.setContext(e.toString()); 183 response.connectionClose(); 184 response.done(); 185 }()); 186 } 187 } 188 catch (Error e) 189 { 190 import std.stdio : writeln; 191 192 collectException({logError(e.toString); writeln(e.toString());}()); 193 194 import core.stdc.stdlib : exit; 195 196 exit(-1); 197 } 198 }